<?php

abstract class AchievementEvaluator {
	protected $user;
	protected $achievementDescription = NULL;
	protected $achievement;

	public function __construct(User $user) {
		$this->user = $user;
		if (empty($this->achievementDescription)) {
			throw new Exception("AchievementEvaluator incorrectly defined");
		}
		$this->achievement = BLL::getInstance()->getAchievementByDescription($this->achievementDescription);
		if (empty($this->achievement)) {
			throw new Exception("Achievement " . $this->achievementDescription . " not found in database");
		}
	}

	// return the achievement object associated with this evaluator
	public function getAchievement() {
		return $this->achievement;
	}

	// returns the obtained achievement when the given Answer $answer
	// entitles the user to the achievement, FALSE if otherwise
	abstract public function achievementObtained(PossibleAnswer $answer);
}

class TagCollectorAchievement extends AchievementEvaluator {
	protected $achievementDescription = "The Tag Collector";

	public function achievementObtained(PossibleAnswer $answer) {
		$bll = BLL::getInstance();
		$user = $bll->getActiveUser();
		$answers = $bll->getAll("PossibleAnswer");
		if (count($answers) % 2) {
			$limit = (count($answers) + 1) / 2;
		} else {
			$limit = count($answers) / 2;
		}
		return count($user->answersGiven) == $limit;
	}
}

class EersteStapAchievement extends AchievementEvaluator {
	protected $achievementDescription = "De Eerste Stap";

	public function achievementObtained(PossibleAnswer $answer) {
		$bll = BLL::getInstance();
		$user = $bll->getActiveUser();
		return count($user->answersGiven) == 1;
	}
}

class AlwaysAchievement extends AchievementEvaluator {
	protected $achievementDescription = "Too Easy";

	public function achievementObtained(PossibleAnswer $answer) {
		return TRUE;
	}
}

class PrivateInvestigatorAchievement extends AchievementEvaluator {
	protected $achievementDescription = "Private Investigator";

	public function achievementObtained(PossibleAnswer $answer) {
		return $answer->question->id == 22;
	}
}

class WinningStreakAchievement extends AchievementEvaluator {
	protected $achievementDescription = "Winning Streak";

	public function achievementObtained(PossibleAnswer $answer) {
		if (empty($_SESSION["streak"])) {
			$_SESSION["streak"] = 0;
		}
		if ($answer->id == $answer->question->correctAnswerID) {
			$_SESSION["streak"] += 1;
		} else {
			$_SESSION["streak"] = 0;
		}
		if ($_SESSION["streak"] >= 5) {
			$_SESSION["streak"] = 0;
			return TRUE;
		} else {
			return FALSE;
		}
	}
}

abstract class QuestionGroupAchievement extends AchievementEvaluator {
	protected $goal;
	protected $candidates;

	public function achievementObtained(PossibleAnswer $answer) {
		$score = 0;
		foreach (BLL::getInstance()->getActiveUser()->answersGiven as $answer) {
			if (in_array($answer->question->id, $this->candidates) && $answer->isCorrect()) {
				$score++;
			}
		}
		return $score >= $this->goal;
	}
}

class NetwerkspecialistAchievement extends QuestionGroupAchievement {
	protected $achievementDescription = "Netwerkspecialist";
	protected $goal = 4;
	protected $candidates = array(12, 14, 23, 24, 25, 29, 30, 39);
}

class HistorischBesefAchievement extends QuestionGroupAchievement {
	protected $achievementDescription = "Historisch Besef";
	protected $candidates = array(4, 9, 11, 32, 37);
	protected $goal = 3;
}
